package Mundo;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

import RW.Escritor;
import RW.Lector;


/**
 * Representa un vertice del grafo
 * @author carlos
 *
 */
public class Ciudad 
{
	
	public final static int MINUTOS_EN_UNA_SEMANA = 10080;
	
	public final static String[] dias = {"Do","Lu","Ma","Mi","Ju","Vi","Sa"};
	
	// ------------------------
    // ATRIBUTOS
	// ------------------------
	
	/**
	 * Tiempo que debe esperarse antes de viajar a la siguiente ciudad
	 */
	private int tiempoEspera;
	
	/**
	 * Nombre de la ciudad. 
	 * Cadena de caracteres alfabeticos de longitud entre 1 y 5
	 */
	private String nombre;
	
	/**
	 * Contenedor con los viajes a otra ciudad
	 */
	private ArrayList<Viaje> viajes;
	
	/**
	 * Identificador para poder agregarlos
	 */
	private int id;
	
	private boolean marcado;
	
	private int respMinutosTranscurridos;
	private String respCadenaViajeOptimo;
	

	// temp
//	private int contador=0;
	
	// ------------------------
    // CONSTRUCTOR
	// ------------------------

	public Ciudad(String nombre,int idd,int tiempoEspera) 
	{
		this.tiempoEspera = tiempoEspera;
		this.nombre = nombre;
		marcado=false;
		id=idd;
		viajes=new ArrayList<Viaje>();
		respMinutosTranscurridos = Integer.MAX_VALUE;
		respCadenaViajeOptimo = "";
	}

	//
	//METODOS
	//
	public void agregarViaje(Viaje viaje)
	{
		viajes.add(viaje);
	}
	
	/**
	 * Busca el mejor viaje a una ciudad destino, a cierta hora, un dia de la semana.
	 * @param ciudadDestino
	 * @param dia
	 * @param hora
	 * @param respMinutosTranscurridos Minutos transcurridos en el camino mas corto evaluado hasta el momento
	 * @param respCadena Cadena con la respuesta del camino mas corto evaluado hasta el momento
	 * @param cadena Contiene la respuesta a escribir en el escritor
	 */
	
	//A mi parecer,  despues de echarle cabeza, me parece que la complejidad es de v² porque mire que no se reocrren
	//todas las ciudades sino que nos dan las ciudades, ya las tenemos de entrada en el método, ahora depués nos toca
	//recorrer los viajes y pues ver cual es el mejor. la primera recorrida= v, cuando se comparan para hallar  el
	//óptim,= v², ahora bien, también podría ser n²*v² diciendo que toca buscar la ciudad de origen y la de destino
	//y hacer una vez más la búsqueda
	
	public String buscarCaminoOptimo(Ciudad ciudadDestino,String dia, int  minutosTranscurridos, int[] hora,String cadena) 
	{
		//Escritor.escribir("buscarViajeOptimo(CiudadDestino:"+ciudadDestino.getNombre()+",Dia:"+dia+", minutosTranscurridos:"+minutosTranscurridos+", hora:{"+hora[0]+","+hora[1]+"} ,Cadena:"+cadena);
		if(nombre.equals(ciudadDestino.getNombre()))
		{
			cadena += darLineaCadena(nombre,dia, hora, hora);
			//Escritor.escribir("Camino encontrado:\n"+cadena);
			
			if(minutosTranscurridos < respMinutosTranscurridos)
			{
				respMinutosTranscurridos = minutosTranscurridos;
				respCadenaViajeOptimo = new String(cadena);
				respCadenaViajeOptimo += respMinutosTranscurridos;
				return respCadenaViajeOptimo;
			}
		}
		else
		{
			
			marcado=true;
			for(int i=0; i<viajes.size();i++)
			{
//				contador++;
				Viaje viaje = viajes.get(i);
				Ciudad ciudadDest = viaje.getCiudadDestino();
				if(!ciudadDest.estaMarcado())
				{
					String cadenaHastaAca = new String(cadena);
					
					int minutosTranscurridosHastaAca = minutosTranscurridos;
					String diaHastaAca = new String(dia);
					int[] horaHastaAca = hora.clone();

					cadena += darLineaCadena(nombre,dia, hora, viaje.getHora());

					minutosTranscurridos += (viaje.getHora()[0] - hora[0])*60;
					hora[0] = viaje.getHora()[0];
					
					minutosTranscurridos += viaje.getHora()[1] - hora[1];
					minutosTranscurridos += (diferenciaEntreDias(dia, viaje.getDia()))*1440;
					
					if(minutosTranscurridos < minutosTranscurridosHastaAca)
					{
						minutosTranscurridos += MINUTOS_EN_UNA_SEMANA;
					}
					minutosTranscurridos += viaje.getDemora();
					
					if(minutosTranscurridos<MINUTOS_EN_UNA_SEMANA)
					{
						hora[1] = viaje.getHora()[1];
						dia = viaje.getDia();
						
						// Actualiza el dia, la hora
							int tempMinutos = hora[1] + viaje.getDemora();
							if(tempMinutos >= 60)
							{
								hora[1] = tempMinutos % 60;
								int tempHoras = hora[0] + (tempMinutos)/60;
								if(tempHoras >= 24)
								{
									int tempDia = tempHoras/24;
									hora[0] = tempHoras % 24;
									dia = sumarDias(dia,minutosTranscurridos,tempDia);
								}
								else
								{
									hora[0] = tempHoras;
								}
							}
							else
							{
								hora[1] = tempMinutos;
							}
						respCadenaViajeOptimo = ciudadDest.buscarCaminoOptimo(ciudadDestino, dia,minutosTranscurridos, hora,cadena);
					}
					
					minutosTranscurridos=minutosTranscurridosHastaAca;
					hora=horaHastaAca;
					dia=diaHastaAca;
					cadena=cadenaHastaAca;	
				}
			}
			marcado=false;
		}// Escritor.escribir("entro al for "+contador+" veces");contador=0;
		return respCadenaViajeOptimo;
	}

	private String darLineaCadena(String elNombre, String dia, int[] horaInicioEspera, int[] horaFinEspera) 
	{
		String cadenaMinutosInicioEspera = horaInicioEspera[1]+"";
		if(cadenaMinutosInicioEspera.equals("0"))
			cadenaMinutosInicioEspera+="0";
		else if(cadenaMinutosInicioEspera.length()==1)
			cadenaMinutosInicioEspera = "0" + cadenaMinutosInicioEspera;
		
		String cadenaMinutosFinEspera = horaFinEspera[1]+"";
		if(cadenaMinutosFinEspera.equals("0"))
			cadenaMinutosFinEspera+="0";
		else if(cadenaMinutosFinEspera.length()==1)
			cadenaMinutosFinEspera = "0" + cadenaMinutosFinEspera;

		return elNombre+" "+dia+" "+horaInicioEspera[0]+":"+cadenaMinutosInicioEspera+" "+horaFinEspera[0]+":"+cadenaMinutosFinEspera + "\n";
	}

	public boolean estaMarcado()
	{
		return marcado;
	}
	
	public void agregarLinea(String cadena,String ciudadActual, String dia,int horasInicio,int minutosInicio, int horasFin, int minutosFin)
	{
		cadena += ciudadActual+" "+dia+" "+horasInicio+":"+minutosInicio+" "+horasFin+":"+minutosFin;
	}
	
	/**
	 * Cambia el dia de la semana de la ciudad al avanzar tempDias
	 * @param dia
	 * @param minutosTranscurridos
	 * @param tempDia
	 * @return string con el dia de la semana. Null si ha transcurrido mas de una semana en el camino que se esta evaluando.
	 */
	public String sumarDias(String dia, int minutosTranscurridos,int tempDia) 
	{
		minutosTranscurridos+=(tempDia*60*24);
			for (int i = 0; i < dias.length; i++) 
			{
				if (dias[i].equals(dia))
				{
					return dias[(i+tempDia)%7];
				}
			}
			return null;
	}
	
	
	/**
	 * Indica cuantos dias pasan entre dos dias de la semana
	 * @param dia1
	 * @param dia2
	 * @return
	 */
	public int diferenciaEntreDias(String dia1, String dia2)
	{
		if(dia1.equals(dia2))
			return 0;
		
		for (int i = 0; i < dias.length; i++) 
		{
			if(dia1.equals(dias[i]))
			{
				for (int j = 0; j < dias.length; j++) 
				{
					if (dia2.equals(dias[j]))
					{
						return  (j-i)>0  ? j-i : (j+7)-i;
					}
				}
			}		
		}
		return -1; // no debe pasar nunca
	}
	
	public void desmarcar()
	{
		marcado=false;
	}
	
	public void prepararBusqueda() 
	{
		respMinutosTranscurridos = Integer.MAX_VALUE;
		respCadenaViajeOptimo = "";
	}
	
	
	// ------------------------
    // GET/SET
	// ------------------------
	
	public int getTiempoEspera() {
		return tiempoEspera;
	}

	public void setTiempoEspera(int tiempoEspera) {
		this.tiempoEspera = tiempoEspera;
	}

	public String getNombre() {
		return nombre;
	}

	public void setNombre(String nombre) {
		this.nombre = nombre;
	}
	
	public int getId()
	{
		return this.id;
	}
	
	public ArrayList<Viaje> getViajes() {
		return viajes;
	}
	
	public String getRespuesta()
	{
		return respCadenaViajeOptimo;
	}
}
